/*
 * Created on Oct 26, 2004
 *
 */
package com.erclab.internal.xpresso;


import org.apache.log4j.Logger;

import com.erclab.internal.xpresso.cache.CacheManager;
import com.erclab.internal.xpresso.cache.CachedElement;
import com.erclab.internal.xpresso.conf.*;
import com.erclab.internal.xpresso.dataAccess.ApplicationDataSource;
import com.erclab.internal.xpresso.dataAccess.ReportDAO;
import com.erclab.internal.xpresso.exceptions.DataSourceException;
import com.erclab.internal.xpresso.exceptions.ReportException;
import com.erclab.internal.xpresso.reports.*;
import com.erclab.internal.xpresso.util.ExceptionUtil;

/**
 * @author rodrigen
 *
 */
public class ReportFactory extends ObjectFactory {

	private static final Logger log = Logger.getLogger(ReportFactory.class);
	
	public static Report loadReport(String reportName) throws ReportException{
		CacheManager cacheManager = Settings.getCacheManager();
		Report reportCached = (Report)cacheManager.getResource(reportName);
		if (reportCached != null) return reportCached;
		
		ReportDAO dao = Settings.getRepository().getDaoFactory().getReportDAO();		
    	Report theReport = dao.createReport(reportName);
    	if(theReport == null)
    		throw new ReportException("The report '" + reportName + "' could not be found in the repository.");
    	
		String reportHelperClass = theReport.getReportHelperClass();
		if (reportHelperClass != null && !reportHelperClass.equals(""))
			loadReportHelper(reportHelperClass, theReport);
    	
		dao.loadReportElements(theReport);
		dao.loadReportFilters(theReport);
		dao.loadReportViews(theReport);
		
		cacheManager.addResource(reportName, new CachedElement(theReport));    
		
		return theReport;
	}


	/**
	 * @param theReport
	 * @return
	 */
	public static ReportResultSet executeReportQuery(Report theReport) throws SecurityException, Exception {
		// Check permission to run this report
		if (!Settings.getAccessController().isAllowedToUseResource(theReport, theReport.getReportParameters().getUser())){
			throw new SecurityException(ExceptionUtil.getSecurityExceptionString(theReport));
		}
		
		if (theReport.getReportHelper() != null)
			theReport.getReportHelper().beforeReportExecution(theReport);
		
		ReportResultSet rrs = (ReportResultSet)Settings.getCacheManager().getResource(
			theReport.getReportName() + XpressoConstants.REPORT_RESULTSET);  
			
		if (rrs == null) {
			log.info("Report Data is not in cache. Querying datasource");
			rrs = createReportResultSet(theReport); 
		} else {
			log.info("Report Data retrieved from cache");
			rrs.moveBeforeFirst();
		}

		if (theReport.getReportHelper() != null)
			theReport.getReportHelper().afterReportExecution(theReport);

		theReport.setReportResultSet(rrs);
		return rrs;
	}
	
	protected static ReportResultSet createReportResultSet(Report theReport) throws DataSourceException {
		ApplicationDataSource ads = Settings.getRepository().getApplicationDataSource(theReport.getIdDatasource());
		ReportResultSet rrs = ads.runReportQuery(theReport);
		rrs.setParameters(theReport.getParameters());
		Settings.getCacheManager().addResource(
				theReport.getReportName() + XpressoConstants.REPORT_RESULTSET, new CachedElement(rrs));
		return rrs;
	}

	protected static void loadReportHelper(String reportHelperClass, Report report) throws ReportException {
		ReportHelper rh = null;
		try {
			Class reportHelper = Class.forName(reportHelperClass);
			rh = (ReportHelper) reportHelper.newInstance();
			report.setReportHelper(rh);
		} catch(ClassNotFoundException e){
			throw new ReportException("The class: " + reportHelperClass + " could not be found." + e);
		} catch(IllegalAccessException e){
			throw new ReportException("IllegalAccessException: " + e);
		} catch(InstantiationException e){
			throw new ReportException("InstantiationException" + e);				
		}
	}
	
}
